﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NLua;
using Sl.Log;
using System.Threading;
using ChholCmdPort;

namespace ChholConfig {
	internal class LuaCmd:IDisposable {
		LuaThread lua_thread=null; 
		public void doLua(string lua_str) => lua_thread.doLua(lua_str);
		public Logger Lua_log { get; set; }
		private PortUserHandle port_user;
		public LuaCmd(PortUserHandle port_user, Logger lua_log=null) {
			Lua_log = lua_log is null ? Program.Log : lua_log;
			this.port_user = port_user;
			port_user.dRecvPkg = recvPkg;
		}
		int recvID_Count = 0;
		private bool recvPkg(Pkg pkg) {
			if (lua_thread is null) return false;
			try {
				lua_thread.run(lua => {
					try { 
						if (lua.IsExecuting) {
							Console.WriteLine("等待lua执行完成");
							while (lua.IsExecuting) ;
						}
						string table_name = $"recv_data{recvID_Count++}";
						lua.NewTable(table_name);
						var recv_data = (LuaTable)lua[table_name];
						recv_data["addr"] = pkg.Remote_addr;
						recv_data["port"] = pkg.From_port;
						for (int i = 0; i < pkg.Data_len; i++) {
							recv_data[i + 1] = pkg[i];
						}
						(lua["__receive"] as LuaFunction).Call(recv_data);
					} catch (Exception e) {
						Lua_log.LogLine($"【错误】收到包{pkg}时递送给lua发生错误\n{e.Message}");
					}
				});
				return true;
			} catch (System.Runtime.InteropServices.SEHException e) {
				Lua_log.LogLine($"【错误】接收中发送错误:\n{e.Message}");
				return false;
			}
				
		}

		public void send__(NLua.LuaTable data) {
			try {
				var pkg = new Pkg();
				pkg.To_port = (byte)(long)data["port"];
				pkg.Remote_addr = (ushort)(long)data["addr"];
				for (int i = 0; i < data.Keys.Count - 2; i++) {
					pkg[i] = (byte)(long)data[i + 1];
				}
				pkg.Data_len = data.Keys.Count - 2;
				port_user.sendPkg(pkg);
			} catch (System.NullReferenceException e) {
				Lua_log.LogLine($"【错误】send中发送错误:\n{e.Message}");
			}
		}
		public void chhol__(string code){
			byte port = port_user.Port_id;
			try {
				Pkg p;
				string res = ChholCode.codeToPkg(code, port, out p);
				if (res != null) {
					Lua_log.LogLine($"【错误】发送指令时发生错误：\n{res}");
					return;
				}else {
					port_user.sendPkg(p);
				}
			} catch (System.NullReferenceException e) {
				Lua_log.LogLine($"【错误】cmd中发送错误:\n{e.Message}");
			}
		}


		public void repeat(int ms, LuaFunction cb) {

		}
		string[] lua_reg_func = { "send__", "chhol__" };



		public void restartLua() {
			if (lua_thread != null) {
				lua_thread.Dispose();
				lua_thread = null;
			}
			startLua();
		}
		public void startLua() {
			if (lua_thread != null) {
				Lua_log.LogLine($"【错误】启动Lua脚本时，还有一个Lua线程尚在运行。");
			}
			lua_thread = new LuaThread(Lua_log);
			lua_thread.run(lua => {
				foreach (string s in lua_reg_func) {
					lua.RegisterFunction(s, this, this.GetType().GetMethod(s));
				}
			});
			return;
		}

		public void Dispose() {
			lua_thread?.Dispose();
		}



	}
	
}